package com.sikaryofficial.backend.service.user;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sikaryofficial.backend.domain.dto.resp.UserLocalDTO;
import com.sikaryofficial.backend.domain.entity.PointsBalance;
import com.sikaryofficial.backend.resolver.PropertiesTools;
import com.sikaryofficial.backend.service.IPointsBalanceService;
import com.sikaryofficial.common.core.exception.ServiceException;
import com.sikaryofficial.common.redis.service.RedisService;
import com.sikaryofficial.common.security.utils.SecurityUtils;
import com.sikaryofficial.system.api.domain.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static com.sikaryofficial.backend.constant.i18n.ExceptionConstant.POINTS_NO_ENOUGH;
import static com.sikaryofficial.common.core.constant.CacheConstants.*;

/**
 * @author : qinjinyuan
 * @desc : 用户缓存对象
 * @date : 2023/11/06 11:02
 */
@Service
@Slf4j
public class UserCacheService {
    @Autowired
    private RedisService redisService;
    @Value("${hismk.backend.store.defaultLon:-1.1339339}")
    private String longitude;
    @Value("${hismk.backend.store.defaultLat:52.6371532}")
    private String latitude;
    @Autowired
    private IPointsBalanceService pointsBalanceService;
    @Resource
    private PropertiesTools propertiesTools;

    /**
     * 个人积分余额校验
     *
     * @param userId
     * @return
     */
    public void verifyUserPoints(Long userId, Integer points) {
        if (verifyPoints(userId, points)) {
            log.error("个人积分余额不存在 | 余额小于当前积分");
            throw new ServiceException(propertiesTools.getProperties(POINTS_NO_ENOUGH));
        }
    }

    public boolean verifyPoints(Long userId, Integer points) {
        PointsBalance pointsBalance = this.getBalanceById(userId);
        return Objects.isNull(pointsBalance) || pointsBalance.getBalance() < points;
    }

    public PointsBalance getBalanceById(Long userId) {
        if (Objects.isNull(userId) || userId <= 0L) {
            return null;
        }
        String balanceCacheKey = buildBalanceCacheKey(userId);
        if (Boolean.TRUE.equals(redisService.hasKey(balanceCacheKey))) {
            return redisService.getCacheObject(buildBalanceCacheKey(userId));
        }
        PointsBalance pointsBalance = pointsBalanceService.getPointsBalanceByUserId(userId);
        redisService.setCacheObject(balanceCacheKey, pointsBalance, 5L, TimeUnit.SECONDS);
        return pointsBalance;
    }

    public void removeBalanceCache(Long userId) {
        if (Objects.isNull(userId) || userId <= 0L) {
            return;
        }
        redisService.deleteObject(buildBalanceCacheKey(userId));
    }

    private String buildBalanceCacheKey(Long userId) {
        return MessageFormat.format(USER_POINTS_BALANCE, String.valueOf(userId));
    }

    /**
     * 缓存用户经纬度
     */
    public void setUserLocalInfo(Double longitude, Double latitude) {
        if (Objects.isNull(longitude) || Objects.isNull(latitude)) {
            return;
        }
        UserLocalDTO userLocalDTO = new UserLocalDTO();
        userLocalDTO.setLongitude(longitude);
        userLocalDTO.setLatitude(latitude);
        log.info("设置用户位置信息:{}", userLocalDTO);
        redisService.setCacheObject(buildLocalCacheKey(SecurityUtils.getUserId()), userLocalDTO);
    }

    private String buildLocalCacheKey(Long userId) {
        return MessageFormat.format(USER_LON_LAT, String.valueOf(userId));
    }

    /**
     * 获取用户缓存经纬度
     * 如果没有，则使用默认经纬度
     *
     * @return
     */
    public UserLocalDTO getUserLocalInfo() {
        UserLocalDTO obj = redisService.getCacheObject(buildLocalCacheKey(SecurityUtils.getUserId()));
        if (Objects.isNull(obj)) {
            obj = new UserLocalDTO();
            obj.setLongitude(Double.valueOf(longitude));
            obj.setLatitude(Double.valueOf(latitude));
        }
        return obj;
    }

    /**
     * 根据brandTasteIds数组，返回对应产品列表
     *
     * @param userIds 用户ID
     * @return 缓存数组
     */
    public Map<Long, String> getMultiUserAvatar(List<Long> userIds) {
        Map<Long, String> result = Maps.newHashMap();
        if (CollUtil.isEmpty(userIds)) {
            return result;
        }
        Set<String> stringHashSet = Sets.newHashSet();
        userIds.forEach(id -> stringHashSet.add(String.valueOf(id)));
        List<SysUser> multiCacheMapValue = redisService.getMultiCacheMapValue(USER_AVATAR_URL, Lists.newArrayList(stringHashSet));
        multiCacheMapValue.removeIf(Objects::isNull);
        // 设置图片路径
        if (CollUtil.isNotEmpty(multiCacheMapValue)) {
            multiCacheMapValue.forEach(sysUser -> {
                if (Objects.isNull(sysUser)) {
                    return;
                }
                result.put(sysUser.getUserId(), sysUser.getAvatar());
            });
        }
        return result;
    }

    /**
     * 根据brandTasteId，返回对应产品
     *
     * @return 缓存对象
     */
    public String getSignUserAvatar(Long userId) {
        if (Objects.isNull(userId) || userId <= 0L) {
            return "";
        }
        SysUser sysUser = redisService.getCacheMapValue(USER_AVATAR_URL, userId.toString());
        return Objects.nonNull(sysUser) ? sysUser.getAvatar() : "";
    }


    /**
     * 根据brandTasteIds数组，返回对应产品列表
     *
     * @param userIds 用户ID
     * @return 缓存数组
     */
    public Map<Long, String> getMultiUserNickName(List<Long> userIds) {
        Map<Long, String> result = Maps.newHashMap();
        if (CollUtil.isEmpty(userIds)) {
            return result;
        }
        Set<String> stringHashSet = Sets.newHashSet();
        userIds.forEach(id -> stringHashSet.add(String.valueOf(id)));
        List<SysUser> multiCacheMapValue = redisService.getMultiCacheMapValue(USER_AVATAR_URL, Lists.newArrayList(stringHashSet));
        multiCacheMapValue.removeIf(Objects::isNull);
        // 设置图片路径
        if (CollUtil.isNotEmpty(multiCacheMapValue)) {
            multiCacheMapValue.forEach(sysUser -> {
                if (Objects.isNull(sysUser)) {
                    return;
                }
                result.put(sysUser.getUserId(), sysUser.getNickName());
            });
        }
        return result;
    }

    /**
     * 根据userId，返回NickName
     *
     * @return 缓存对象
     */
    public String getSignUserNickName(Long userId) {
        if (Objects.isNull(userId) || userId <= 0L ) {
            return "";
        }
        SysUser sysUser = redisService.getCacheMapValue(USER_AVATAR_URL, userId.toString());
        return Objects.nonNull(sysUser) ? sysUser.getNickName() : "";
    }

    public String getAccountById(Long userId) {
        if (Objects.isNull(userId) || userId <= 0L ) {
            return "";
        }
        SysUser sysUser = redisService.getCacheMapValue(USER_AVATAR_URL, userId.toString());
        return Objects.nonNull(sysUser) ? sysUser.getUserName() : "";
    }

    public String getSignUserEmail(Long userId) {
        if (Objects.isNull(userId) || userId <= 0L) {
            return "";
        }
        SysUser sysUser = redisService.getCacheMapValue(USER_AVATAR_URL, userId.toString());
        return Objects.nonNull(sysUser) ? sysUser.getEmail() : "";
    }

    /**
     * 根据userId，返回SysUser
     *
     * @return 缓存对象
     */
    public SysUser getSysUser(Long userId) {
        if (Objects.isNull(userId)) {
            return null;
        }
        return redisService.getCacheMapValue(USER_AVATAR_URL, userId.toString());
    }

    public void setSysUser(Long userId, SysUser user) {
        if (Objects.isNull(userId) || Objects.isNull(user)) {
            return;
        }
        redisService.setCacheMapValue(USER_AVATAR_URL, userId.toString(), user);
    }

}
